﻿#region Header

/*
    This file is part of ndoctor-statistics.

    ndoctor-statistics is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ndoctor-statistics is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ndoctor-statistics.  If not, see <http://www.gnu.org/licenses/>.
*/

#endregion Header

namespace Probel.NDoctor.Statistics
{
    using System;

    using FluentNHibernate.Cfg;
    using FluentNHibernate.Cfg.Db;

    using NHibernate;
    using NHibernate.Cfg;
    using NHibernate.Tool.hbm2ddl;

    using Probel.NDoctor.Statistics.Loggers;
    using Probel.NDoctor.Statistics.Mappings;

    internal class MySqlSessionFactoryBuilder
    {
        #region Fields

        private readonly string Database;
        private readonly string Password;
        private readonly string Server;
        private readonly string UserName;

        private static ISessionFactory factory;

        #endregion Fields

        #region Constructors

        public MySqlSessionFactoryBuilder(string server, string username, string password, string database)
        {
            this.Server = server;
            this.UserName = username;
            this.Password = password;
            this.Database = database;
            LoggingService.Instance.DebugFormat("{0}@{1} -  User: {2}"
                , this.Database
                , this.Server
                , this.UserName);
        }

        #endregion Constructors

        #region Properties

        private IPersistenceConfigurer MySql
        {
            get
            {
                return MySQLConfiguration
                    .Standard
                    .Driver<NHibernate.Driver.MySqlDataDriver>()
                    .ConnectionString(s =>
                    {
                        s.Server(this.Server);
                        s.Database(this.Database);
                        s.Username(UserName);
                        s.Password(Password);
                    });
            }
        }

        #endregion Properties

        #region Methods

        public ISessionFactory BuildFactory(bool doUpdateDatabase = false, bool doCreateNewDatabase = false)
        {
            if (factory == null)
            {
                try
                {
                    factory = Fluently.Configure()
                        .Database(MySql)
                        .Mappings(map => map.AutoMappings.Add(new MyAutoPersistenceModel()))
                        .ExposeConfiguration(cfg => this.ExposeConfiguration(cfg, doCreateNewDatabase, doUpdateDatabase))
                        .BuildSessionFactory();
                }
                catch (Exception ex)
                {
                    throw new ApplicationException("An error occured when creating the nHibernate session factory", ex);
                }
            }
            return factory;
        }

        private void ExposeConfiguration(Configuration cfg, bool doCreateNewDatabase, bool doUpdateDatabase)
        {
            if (doCreateNewDatabase)
            {
                LoggingService.Instance.DebugFormat("Creating database...", doCreateNewDatabase);
                new SchemaExport(cfg).Create(false, true);
            }
            if (doUpdateDatabase && !doCreateNewDatabase)
            {
                LoggingService.Instance.DebugFormat("Updating the database...");
                new SchemaUpdate(cfg).Execute(false, true);
            }
        }

        #endregion Methods
    }
}